﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Threading;
using NXOpen;
using NXOpen.BlockStyler;
using System.IO;
using System.Xml;
using NXOpen.UF;
using NXOpen.Routing;
using NXOpen.Features;
using NXOpen.Utilities;
using UGCommon;

using System.Text.RegularExpressions;
using System.Data;
//using MathNet.Numerics;
//using MathNet.Numerics.LinearAlgebra;
//using MathNet.Numerics.LinearAlgebra.Complex;
//using MathNet.Numerics.LinearAlgebra.Factorization;
//using MathNet.Numerics.LinearAlgebra.Double;



namespace REAStar
{
    [Serializable]
    public class GridInfo
    {
        private static UFSession theUFSession = UFSession.GetUFSession();
        private Part workPart;
        private NXOpen.Session theSession = NXOpen.Session.GetSession();
        UGComponent ugcomponent = new UGComponent();

        public UFAssem assem = null;
        List<NXOpen.Assemblies.Component> allComponents = new List<NXOpen.Assemblies.Component>(); //存放所有组件
        List<NXOpen.Assemblies.Component> allComponentsWithoutChildren = new List<NXOpen.Assemblies.Component>(); //存放所有没有子组件的组件
        NXOpen.Assemblies.Component[] allFirstChildrenComponents; //存放第一级子组件的数组
        List<NXOpen.Assemblies.Component> allFirstChildrenComponentsList = new List<NXOpen.Assemblies.Component>();//存放第一级子组件的列表
        public List<string> allFirstChildrenComponentName = new List<string>();//存放第一级子组件组件的名称
        List<string> allPART_DB_NAME = new List<string>(); //存放所有部件名
        List<NXOpen.Assemblies.Component> pipeComponents = new List<NXOpen.Assemblies.Component>(); //存放所有管路组件
        List<NXOpen.Assemblies.Component> otherComponents = new List<NXOpen.Assemblies.Component>(); //存放需要避障的非管路组件
        List<NXOpen.Assemblies.Component> bigComponents = new List<NXOpen.Assemblies.Component>(); //存放大的非管路组件 机匣等
        List<NXOpen.Assemblies.Component> smallComponents = new List<NXOpen.Assemblies.Component>(); //存放小的非管路组件 螺钉等
        List<int> allPipeMatchi = new List<int>(); //存放所有符合名称为导管的下标
        List<int> otherBodyMatchi = new List<int>(); //存放所有名称不为导管的下标
        List<Body> pipeBody = new List<Body>();//存放所有符合名称为导管的体
        List<Body> otherBody = new List<Body>();//存放所有非导管的体
        List<Tag> pipeBodyTag = new List<Tag>();//管路tag
        List<Tag> otherBodyTag = new List<Tag>();//非管路tag

        List<List<Line>> allPipeLine = new List<List<Line>>();//存放所有管路的管线
        UGComponent ugComp = new UGComponent();
        public GridInfo()
        {
        }

        public List<OBB> getAllComponentOBB()
        {
            #region 获取所有一级子组件的包围盒
            //List<OBB> boundingBoxOfOBB = new List<OBB>();//存放所有组件OBB包围盒
            //List<NXOpen.Assemblies.Component> firstChildrenPipeComponents = new List<NXOpen.Assemblies.Component>(); //存放所有管路组件
            //List<NXOpen.Assemblies.Component> firstChildrenOtherComponents = new List<NXOpen.Assemblies.Component>(); //存放需要避障的非管路组件
            //List<NXOpen.Assemblies.Component> firstChildrenBigComponents = new List<NXOpen.Assemblies.Component>(); //存放大的非管路组件

            ////隐藏状态的第一级子组件去除
            //for (int i = allFirstChildrenComponentsList.Count - 1; i >= 0; i--)
            //{
            //    //判断该组件是否成功加载
            //    NXOpen.Assemblies.Component[] componentsToOpen1 = new NXOpen.Assemblies.Component[1];
            //    componentsToOpen1[0] = allFirstChildrenComponentsList[i];
            //    NXOpen.Assemblies.ComponentAssembly.OpenComponentStatus[] openStatus1;
            //    NXOpen.PartLoadStatus partLoadStatus1;
            //    partLoadStatus1 = workPart.ComponentAssembly.OpenComponents(NXOpen.Assemblies.ComponentAssembly.OpenOption.WholeAssembly, componentsToOpen1, out openStatus1);
            //    if (openStatus1[0].ToString() == "SuccessfullyOpened")
            //    {
            //        //判断是否为隐藏状态
            //        bool tmpIsBlank = allFirstChildrenComponentsList[i].IsBlanked;
            //        if (tmpIsBlank)
            //        {
            //            allFirstChildrenComponentsList.Remove(allFirstChildrenComponentsList[i]);
            //        }
            //    }
            //}
            ////通过DB_PART_NAME 获取需要加入管理的第一级子组件
            //for (int i = 0; i < allFirstChildrenComponentsList.Count; i++)
            //{
            //    string tmpPartName = "";
            //    try
            //    {
            //        tmpPartName = allFirstChildrenComponentsList[i].GetStringAttribute("DB_PART_NAME");
            //        if (tmpPartName == "导管" || tmpPartName == "管路")
            //        {
            //            firstChildrenPipeComponents.Add(allFirstChildrenComponentsList[i]);
            //        }
            //        else if (tmpPartName == "中介机匣" || tmpPartName == "涡扇机匣" || tmpPartName == "燃烧室机匣" || tmpPartName == "涡扇" || tmpPartName == "涡轮")
            //        {
            //            firstChildrenBigComponents.Add(allFirstChildrenComponentsList[i]);
            //        }
            //        else
            //        {
            //            firstChildrenOtherComponents.Add(allFirstChildrenComponentsList[i]);
            //        }
            //    }
            //    catch
            //    {
            //        tmpPartName = "0";
            //    }
            //}


            ////将每个非导管的第一级子组件生成包围盒
            //for (int i = 0; i < firstChildrenOtherComponents.Count; i++)
            //{
            //    OBB OBB = new OBB(firstChildrenOtherComponents[i]);
            //    boundingBoxOfOBB.Add(OBB);
            //}
            #endregion

            #region 获取所有没有子组件的组件的包围盒
            workPart = theSession.Parts.Work;
            assem = theUFSession.Assem;
            Tag tmpCompo = assem.AskRootPartOcc(workPart.Tag);
            NXOpen.Assemblies.Component rootCompo = (NXOpen.Assemblies.Component)NXObjectManager.Get(tmpCompo);
            allFirstChildrenComponents = rootCompo.GetChildren();
            for (int i = 0; i < allFirstChildrenComponents.Length; i++)
            {
                allFirstChildrenComponentsList.Add(allFirstChildrenComponents[i]);
            }
            getAllComponent(allFirstChildrenComponents);
            allComponentsWithoutChildren.Distinct().ToList();

            //隐藏状态的组件去除
            for (int i = allComponentsWithoutChildren.Count - 1; i >= 0; i--)
            {
                //判断该组件是否成功加载
                NXOpen.Assemblies.Component[] componentsToOpen1 = new NXOpen.Assemblies.Component[1];
                componentsToOpen1[0] = allComponentsWithoutChildren[i];
                NXOpen.Assemblies.ComponentAssembly.OpenComponentStatus[] openStatus1;
                NXOpen.PartLoadStatus partLoadStatus1;
                partLoadStatus1 = workPart.ComponentAssembly.OpenComponents(NXOpen.Assemblies.ComponentAssembly.OpenOption.WholeAssembly, componentsToOpen1, out openStatus1);
                if (openStatus1[0].ToString() == "SuccessfullyOpened")
                {
                    //判断是否为隐藏状态
                    bool tmpIsBlank = allComponentsWithoutChildren[i].IsBlanked;
                    if (tmpIsBlank)
                    {
                        allComponentsWithoutChildren.Remove(allComponentsWithoutChildren[i]);
                    }
                }
            }

            //通过DB_PART_NAME 获取需要加入管理的组件
            for (int i = 0; i < allComponentsWithoutChildren.Count; i++)
            {
                string tmpPartName = "";
                try
                {
                    int value = -1;
                    theUFSession.Attr.FindAttribute(allComponentsWithoutChildren[i].Tag, 5, "DB_PART_NAME", out value);//判断组件的"DB_PART_NAME"属性是否存在 返回0则是没有"DB_PART_NAME"属性
                    //if (value != 0)
                    //{
                        tmpPartName = allComponentsWithoutChildren[i].GetStringAttribute("DB_PART_NAME");
                    //}
                    //else
                    //{
                    //    tmpPartName = "0";
                    //}

                    //tmpPartName = allComponentsWithoutChildren[i].GetStringAttribute("DB_PART_NAME");
                    if (tmpPartName == "导管" || tmpPartName == "管路" || tmpPartName == "管子" /*|| tmpPartName == "软管"*/)
                    {
                        pipeComponents.Add(allComponentsWithoutChildren[i]);
                    }
                    else if (tmpPartName == "中介机匣" || tmpPartName == "涡扇机匣" || tmpPartName == "燃烧室机匣" || tmpPartName == "涡扇" || tmpPartName == "涡轮" || tmpPartName == "新研成附件小平面体" || tmpPartName.Contains("壳体"))
                    {
                        bigComponents.Add(allComponentsWithoutChildren[i]);
                    }
                    else if (tmpPartName.Contains("挡圈")  || tmpPartName.Contains("螺钉") || tmpPartName == "圆截面橡胶圈密封结构" || tmpPartName.Contains("螺栓")|| tmpPartName == "圆截面橡胶圈密封结构")
                    {
                        smallComponents.Add(allComponentsWithoutChildren[i]);
                    }
                    else if (tmpPartName.Contains("测压管") || tmpPartName.Contains("通风管") || tmpPartName.Contains("圆截面橡胶") || tmpPartName.Contains("双耳托板游") || tmpPartName.Contains("管") || tmpPartName.Contains("圆截面橡胶") || tmpPartName.Contains("自锁螺母") || tmpPartName.Contains("胶圈") || tmpPartName.Contains("接头堵") || tmpPartName.Contains("密封圈"))
                    {

                    }
                    else
                    {
                        otherComponents.Add(allComponentsWithoutChildren[i]);
                    }
                }
                catch
                {
                    tmpPartName = "0";
                }
            }

            List<OBB> boundingBoxOfOBB = new List<OBB>();//存放所有没有子组件的组件的OBB包围盒
            for (int i = 0; i < otherComponents.Count; i++)
            {
                OBB OBB = new OBB(otherComponents[i]);
                boundingBoxOfOBB.Add(OBB);
            }
            
            #endregion
            return boundingBoxOfOBB;
        }

        public List<OBB> getAllPipeLineOBB()
        {
            List<OBB> boundingBoxOfOBB = new List<OBB>();//存放所有直管段OBB包围盒
            List<List<List<double[]>>> allPipeEndStartPointList = new List<List<List<double[]>>>();//存放所有管路直管段的开始点和终止点坐标
            List<double> allPipeDia = new List<double>();//存放所有管路直径

            List<List<LineSegment>> allPipeLineSegment = new List<List<LineSegment>>();//所有管路的中心线直线段集合
            allPipeEndStartPointList = new List<List<List<double[]>>>();//所有的管路组件中管线直线段起始终止坐标 第一个List是管路的List 第二个List是一个管路上管线的List 第二个List是两个double数组 double数组是一条管线的起点或者终点
            allPipeDia = new List<double>();//所有的管路的直径


            //获取所有管路组件的中心线集合
            for (int i = 0; i < pipeComponents.Count; i++)
            {
                PartLoadStatus partLoadStatus1;
                theSession.Parts.SetWorkComponent(pipeComponents[i], out partLoadStatus1);//工作部件设置为具体的管路

                UGPipe tmpPipe = new UGPipe(pipeComponents[i]);
                UGComponent ugComp = new UGComponent();
                Tag pipe_Tag = ugComp.GetBodyTagFromComponent(pipeComponents[i])[0];
                Body tmpPipeBody = (Body)NXObjectManager.Get(pipe_Tag);
                tmpPipe.pipeBody = tmpPipeBody;
                tmpPipe.getPipeOuterDiameter();//把管路直径求出来;
                List<LineSegment> tmpPipeLine = new List<LineSegment>();//每条管路的所有直线
                List<ArcSegment> tmpPipeBend = new List<ArcSegment>();//每条管路的所有折弯线
                getPipeLineSegment(tmpPipeBody, out tmpPipeLine, out tmpPipeBend);

                allPipeLineSegment.Add(tmpPipeLine);
                allPipeDia.Add(tmpPipe.outerDiameter);


                List<List<double[]>> tmpPipeCtrPoint = new List<List<double[]>>();//一条管路上的所有控制点
                for (int j = 0; j < tmpPipeLine.Count; j++)
                {
                    List<double[]> ctrPoint = new List<double[]>();
                    double[] lineStartPoint = new double[3] { allPipeLineSegment[i][j].StartPoint.X, allPipeLineSegment[i][j].StartPoint.Y, allPipeLineSegment[i][j].StartPoint.Z };
                    double[] ctrPointStart = transPointCoor(lineStartPoint);
                    double[] lineEndPoint = new double[3] { allPipeLineSegment[i][j].EndPoint.X, allPipeLineSegment[i][j].EndPoint.Y, allPipeLineSegment[i][j].EndPoint.Z };
                    double[] ctrPointEnd = transPointCoor(lineEndPoint);
                    ctrPoint.Add(ctrPointStart);
                    ctrPoint.Add(ctrPointEnd);
                    tmpPipeCtrPoint.Add(ctrPoint);
                }
                allPipeEndStartPointList.Add(tmpPipeCtrPoint);
                theSession.Parts.SetWork(workPart); 
            }

            for (int i = 0; i < allPipeEndStartPointList.Count; i++)
            {
                for (int j = 0; j < allPipeEndStartPointList[i].Count; j++)
                {
                    OBB pipeOBB = new OBB(allPipeEndStartPointList[i][j][0], allPipeEndStartPointList[i][j][1], allPipeDia[i]);
                    boundingBoxOfOBB.Add(pipeOBB);
                }
            }

            return boundingBoxOfOBB;
        }
        public List<pipeS> getAllPipecmps()
        {
            List<pipeS> tempipes = new List<pipeS>();
            List<OBB> boundingBoxOfOBB = new List<OBB>();//存放所有直管段OBB包围盒
            List<List<List<double[]>>> allPipeEndStartPointList = new List<List<List<double[]>>>();//存放所有管路直管段的开始点和终止点坐标
            List<double> allPipeDia = new List<double>();//存放所有管路直径

            List<List<LineSegment>> allPipeLineSegment = new List<List<LineSegment>>();//所有管路的中心线直线段集合
            allPipeEndStartPointList = new List<List<List<double[]>>>();//所有的管路组件中管线直线段起始终止坐标 第一个List是管路的List 第二个List是一个管路上管线的List 第二个List是两个double数组 double数组是一条管线的起点或者终点
            allPipeDia = new List<double>();//所有的管路的直径

            UGTools.writeInListWindow(pipeComponents.Count.ToString());
            //获取所有管路组件的中心线集合
            for (int i = 0; i < pipeComponents.Count; i++)
            {
                PartLoadStatus partLoadStatus1;
                theSession.Parts.SetWorkComponent(pipeComponents[i], out partLoadStatus1);//工作部件设置为具体的管路

                UGPipe tmpPipe = new UGPipe(pipeComponents[i]);
                UGComponent ugComp = new UGComponent();
                Tag pipe_Tag = ugComp.GetBodyTagFromComponent(pipeComponents[i])[0];
                Body tmpPipeBody = (Body)NXObjectManager.Get(pipe_Tag);
                tmpPipe.pipeBody = tmpPipeBody;
                tmpPipe.getPipeOuterDiameter();//把管路直径求出来;
                List<double[]> pipeOriginalCtrPoints = new List<double[]>();
                List<double[]> pipeLineSegmentlCtrPoints = new List<double[]>();
                OBB tenpobb = new OBB();
                tenpobb.getPipeOriginalCtrPoints(tmpPipe.pipeBody, out pipeOriginalCtrPoints, out pipeLineSegmentlCtrPoints);
              

                for (int j = 0; j < pipeOriginalCtrPoints.Count - 1; j++) // 减1以确保不会超出索引
                {
                    pipeS pp = new pipeS();
                    pp.d = tmpPipe.outerDiameter/2;

                    // 使用当前索引的坐标作为p1
                    pp.p1 = new double[] { pipeOriginalCtrPoints[j][0], pipeOriginalCtrPoints[j][1], pipeOriginalCtrPoints[j][2] };

                    // 使用下一个索引的坐标作为p2
                    pp.p2 = new double[] { pipeOriginalCtrPoints[j + 1][0], pipeOriginalCtrPoints[j + 1][1], pipeOriginalCtrPoints[j + 1][2] };

                    tempipes.Add(pp);
                }
 
                theSession.Parts.SetWork(workPart);
            }
            return tempipes;
        }

        public List<OBB> getAllPipeBendOBB()
        {
            List<OBB> boundingBoxOfOBB = new List<OBB>();//存放所有管路折弯段OBB包围盒
            List<List<List<double[]>>> allPipeBendEndStartPointList = new List<List<List<double[]>>>();//存放所有管路折弯管段的开始点和终止点坐标
            List<double> allfirstChildrenPipeDia = new List<double>();//存放所有管路直径

            List<UGPipe> allfirstChildrenPipe = new List<UGPipe>();//所有的一级子组件中的管路
            List<List<ArcSegment>> allPipeBendSegment = new List<List<ArcSegment>>();//所有的一级子组件中管路的中心线折弯线段集合
            List<List<double[]>> allPipeBendSegmentCenterPoint = new List<List<double[]>>();//所有的一级子组件中管路的中心线折弯线中心点集合
            List<List<double>> allPipeBendSegmentRadius = new List<List<double>>();//所有的一级子组件中管路的中心线折弯线半径集合

            allPipeBendEndStartPointList = new List<List<List<double[]>>>();//所有的一级子组件中管线直线段起始终止坐标 第一个List是管路的List 第二个List是一个管路上管线的List 第二个List是两个double数组 double数组是一条折弯管线的起点或者终点
            allfirstChildrenPipeDia = new List<double>();//所有的一级子组件中的管路的直径

            //获取所有一级子组件中的管路组件的中心线集合
            for (int i = 0; i < pipeComponents.Count; i++)
            {
                PartLoadStatus partLoadStatus1;
                theSession.Parts.SetWorkComponent(pipeComponents[i], out partLoadStatus1);//工作部件设置为具体的管路

                //UGTools.writeInListWindow("firstChildrenPipeComponents" + i.ToString());
                UGPipe tmpPipe = new UGPipe(pipeComponents[i]);
                allfirstChildrenPipe.Add(tmpPipe);

                UGComponent ugComp = new UGComponent();
                Tag pipe_Tag = ugComp.GetBodyTagFromComponent(pipeComponents[i])[0];
                Body tmpPipeBody = (Body)NXObjectManager.Get(pipe_Tag);


                tmpPipe.pipeBody = tmpPipeBody;

                tmpPipe.getPipeOuterDiameter();//把管路直径求出来;
                List<LineSegment> tmpPipeLine = new List<LineSegment>();//每条管路的所有直线
                List<ArcSegment> tmpPipeBend = new List<ArcSegment>();//每条管路的所有折弯线
                getPipeLineSegment(tmpPipeBody, out tmpPipeLine, out tmpPipeBend);

                List<double[]> tmpBendCenterPoint = new List<double[]>(); //每条管路的所有折弯线相应的圆心
                for (int j = 0; j < tmpPipeBend.Count; j++)
                {
                    tmpBendCenterPoint.Add(UGMath.convertPointed3dToArray(tmpPipeBend[j].CenterPoint));
                }
                List<double> tmpBendRadius = new List<double>(); //每条管路的所有折弯线半径
                for (int j = 0; j < tmpPipeBend.Count; j++)
                {
                    tmpBendRadius.Add(tmpPipeBend[j].Radius);
                }
                allPipeBendSegment.Add(tmpPipeBend);
                allPipeBendSegmentCenterPoint.Add(tmpBendCenterPoint);
                allPipeBendSegmentRadius.Add(tmpBendRadius);
                allfirstChildrenPipeDia.Add(tmpPipe.outerDiameter);
                //UGTools.writeInListWindow("tmpPipe.outerDiameter:" + tmpPipe.outerDiameter.ToString());


                //UGTools.writeInListWindow("tmpPipeLine.Count:" + tmpPipeLine.Count.ToString());
                List<List<double[]>> tmpPipeCtrPoint = new List<List<double[]>>();//一条管路上的所有控制点
                for (int j = 0; j < tmpPipeBend.Count; j++)
                {
                    List<double[]> ctrPoint = new List<double[]>();
                    Point3d arcStartPoint3d;
                    Point3d arcEndPoint3d;
                    tmpPipeBend[j].GetEndPoints(out arcStartPoint3d, out arcEndPoint3d);
                    double[] arcStartPoint = UGMath.convertPoint3dToArray(arcStartPoint3d);
                    double[] ctrPointStart = transPointCoor(arcStartPoint);
                    double[] arcEndPoint = UGMath.convertPoint3dToArray(arcEndPoint3d);
                    double[] ctrPointEnd = transPointCoor(arcEndPoint);
                    ctrPoint.Add(ctrPointStart);
                    ctrPoint.Add(ctrPointEnd);
                    tmpPipeCtrPoint.Add(ctrPoint);
                }
                allPipeBendEndStartPointList.Add(tmpPipeCtrPoint);

                theSession.Parts.SetWork(workPart);//工作部件返回为根组件
            }


            for (int i = 0; i < allPipeBendSegment.Count; i++)
            {
                for (int j = 0; j < allPipeBendSegment[i].Count; j++)
                {
                    List<double[]> arcPoints = new List<double[]>();
                    Tag tmpArcPipeTag = allPipeBendSegment[i][j].Tag;
                    double[] scatterPoint = null;
                    int numspt = 0;
                    theUFSession.Modl.AskCurvePoints(tmpArcPipeTag, 0, 30 * Math.PI / 180, 0, out numspt, out scatterPoint); //一条弧上每隔30度生成一个点

                    for (int k = 0; k < scatterPoint.Length; k += 3)
                    {
                        double[] pointNew = new double[3] { scatterPoint[k], scatterPoint[k + 1], scatterPoint[k + 2] };
                        arcPoints.Add(pointNew);
                    }

                    List<double[]> arcPointList = arcPoints;
                    for (int z = 0; z < arcPointList.Count - 1; z++)
                    {
                        OBB pipeOBB = new OBB(arcPointList[z], arcPointList[z + 1], allfirstChildrenPipeDia[i], allPipeBendSegmentRadius[i][j], allPipeBendSegmentCenterPoint[i][j]);
                        boundingBoxOfOBB.Add(pipeOBB);
                    }

                }
            }

            return boundingBoxOfOBB;
        }
        /// <summary>
        /// 通过两点创建一条直线
        /// </summary>
        /// <param name="point1"></param>
        /// <param name="point2"></param>
        public void CreateLineByTwoPoint(double[] point1, double[] point2)
        {
            Part workPart = theSession.Parts.Work;
            Point3d startPoint = UGMath.convertArrayToPoint3d(point1);
            Point3d endPoint = UGMath.convertArrayToPoint3d(point2);
            Line lineData = workPart.Curves.CreateLine(startPoint, endPoint);
            lineData.SetVisibility(SmartObject.VisibilityOption.Visible);
            theUFSession.Obj.SetColor(lineData.Tag, 186);
        }
        /// <summary>
        /// 点在从工作坐标系中的转换到绝对坐标系
        /// </summary>
        /// <param name="absPoint"></param>
        /// <returns></returns>
        public double[] transPointCoor(double[] absPoint)
        {
            double[] surfPtArray = new double[3] { absPoint[0], absPoint[1], absPoint[2] };
            double[] transPoint = new double[3] { 0, 0, 0 };
            //if (true)
            //{
            //    UF_CSYS_WORK_COORDS.
            //}
            theUFSession.Csys.MapPoint(UFConstants.UF_CSYS_WORK_COORDS, surfPtArray, UFConstants.UF_CSYS_ROOT_COORDS, transPoint);
            Point3d workPoint1 = UGMath.convertArrayToPoint3d(transPoint);
            double[] workPoint = new double[3] { workPoint1.X, workPoint1.Y, workPoint1.Z };
            return workPoint;
        }

        /// <summary>
        /// 获取所有的组件
        /// </summary>
        /// <param name="allassembly"></param>
        public void getAllComponent(NXOpen.Assemblies.Component[] allassembly)
        {
            for (int i = 0; i < allassembly.Length; i++)
            {
                //allComponents.Add(allassembly[i]);
                if (allassembly[i].GetChildren().Length > 0)
                {
                    getAllComponent(allassembly[i].GetChildren());
                }
                else
                {
                    allComponentsWithoutChildren.Add(allassembly[i]);
                }
            }
        }

        /// 
        /// 获取直管路段的中心线（LineSegment型）
        /// 返回值：
        /// List<LineSegment> lineAxisList - 管路直段中心线集合
        ///List<ArcSegment> arcAxisList- 管路弯段中心线集合
        public void getPipeLineSegment(Body targetBody, out List<LineSegment> lineAxisList, out List<ArcSegment> arcAxisList)
        {
            lineAxisList = new List<LineSegment>();   //获取直管路段的中心线集合
            arcAxisList = new List<ArcSegment>();   //获取直管路段的中心线集合
            Body tmpPipeBody = targetBody;

            Tag stock_tag;
            theUFSession.Route.AskObjectStock(tmpPipeBody.Tag, out stock_tag);
            NXOpen.Routing.Stock route_stock = (NXOpen.Routing.Stock)NXObjectManager.Get(stock_tag);
            //获取管路的各中心线段
            Curve[] axisPre = route_stock.GetSegments(); ;//整个管路中心线集合

            //排除Curve中的曲线段(ArcSegment)
            Curve tempAxis = null;
            for (int i = 0; i < axisPre.Length; i++)
            {
                string type = axisPre[i].GetType().ToString();
                if (type == "NXOpen.Routing.LineSegment")
                {
                    tempAxis = axisPre[i];
                    lineAxisList.Add((LineSegment)tempAxis);
                }
                if (type == "NXOpen.Routing.ArcSegment")
                {
                    tempAxis = axisPre[i];
                    arcAxisList.Add((ArcSegment)tempAxis);
                }
            }

        }

    }
    [Serializable]
    public class Matrix3
    {
        //	public double m00;
        //	public double m01;
        //	public double m02;
        //	public double m10;
        //	public double m11;
        //	public double m12;
        //	public double m20;
        //	public double m21;
        //	public double m22;
        //	
        public double[] data = new double[9];

        //	public Vector3 a1;
        //	public Vector3 a2;
        //	public Vector3 a3;
        public Matrix3()
        {
        }

        public Matrix3(double m00, double m01, double m02, double m10, double m11, double m12, double m20, double m21, double m22)
        {
            this.data[0] = m00;
            this.data[1] = m01;
            this.data[2] = m02;
            this.data[3] = m10;
            this.data[4] = m11;
            this.data[5] = m12;
            this.data[6] = m20;
            this.data[7] = m21;
            this.data[8] = m22;

        }

        //	public Matrix3(Vector3 a1,Vector3 a2,Vector3 a3){
        //		this.a1=a1;
        //		this.a2=a2;
        //		this.a3=a3;
        //	}

        public Matrix3(double[] data)
        {
            for (int i = 0; i < 9; i++)
                this.data[i] = data[i];
        }
        public Matrix3(Vector3 a1, Vector3 a2, Vector3 a3)
        {
            this.data[0] = a1.x;
            this.data[1] = a1.y;
            this.data[2] = a1.z;
            this.data[3] = a2.x;
            this.data[4] = a2.y;
            this.data[5] = a2.z;
            this.data[6] = a3.x;
            this.data[7] = a3.y;
            this.data[8] = a3.z;

        }

        public Matrix3 clone(Matrix3 matrix3)
        {
            return matrix3;
        }
        //Transpose 
        public Matrix3 transpose()
        {
            return new Matrix3(this.data[0], this.data[3], this.data[6],
                                this.data[1], this.data[4], this.data[7],
                                this.data[2], this.data[5], this.data[8]);
        }

        //Inverse
        public Matrix3 inverse()//返回逆矩阵
        {
            Matrix3 temp = new Matrix3((data[4] * data[8]) - (data[5] * data[7]),
                                    (data[3] * data[8]) - (data[6] * data[5]),
                                    (data[3] * data[7]) - (data[4] * data[6]),
                                    (data[1] * data[8]) - (data[7] * data[2]),
                                    (data[0] * data[8]) - (data[2] * data[6]),
                                    (data[0] * data[7]) - (data[6] * data[1]),
                                    (data[1] * data[5]) - (data[4] * data[2]),
                                    (data[0] * data[5]) - (data[3] * data[2]),
                                    (data[0] * data[4]) - (data[3] * data[1])
                    );
            for (int i = 1; i < 8; i += 2)
                temp.data[i] *= -1;
            temp = temp.transpose();
            temp = Matrix3.divide(temp, temp.determinant());
            return temp;
        }
        //get the element of the matrix 
        public double getColRow(int col, int row)//返回col行，row列的元素
        {
            return data[(3 * col) + row];
        }

        //return the vector
        public Vector3 getRowVector(int num)
        {
            if (num == 1)
                return new Vector3(data[0], data[1], data[2]);
            if (num == 2)
                return new Vector3(data[3], data[4], data[5]);
            if (num == 3)
                return new Vector3(data[6], data[7], data[8]);
            else
                return null;
        }


        public void setColRow(int col, int row, double data)
        {
            this.data[(3 * col) + row] = data;
        }

        //The value of the determinant
        public double determinant()//返回行列式值
        {
            return (data[0] * ((data[4] * data[8]) - (data[5] * data[7]))) -
                   (data[3] * ((data[1] * data[8]) - (data[2] * data[7]))) +
                   (data[6] * ((data[1] * data[5]) - (data[2] * data[4])));

        }
        // "/"
        public static Matrix3 divide(Matrix3 m, double num)
        {
            for (int i = 0; i < 9; i++)
                m.data[i] /= num;
            return m;
        }

        // "*"
        public static Matrix3 multiply(double num, Matrix3 m)
        {
            for (int i = 0; i < 9; i++)
                m.data[i] *= num;
            return m;
        }

        // "+"
        public static Matrix3 add(Matrix3 m1, Matrix3 m2)
        {
            for (int i = 0; i < 9; i++)
                m1.data[i] += m2.data[i];
            return m1;
        }

        //"-"
        public static Matrix3 sub(Matrix3 m1, Matrix3 m2)
        {
            for (int i = 0; i < 9; i++)
                m1.data[i] -= m2.data[i];
            return m1;

        }

        //To create a zero matrix
        public static Matrix3 zero()
        {
            return new Matrix3(0.0f, 0.0f, 0.0f,
                                0.0f, 0.0f, 0.0f,
                                0.0f, 0.0f, 0.0f);
        }

        //To create a identity matrix
        public static Matrix3 identity()
        {
            return new Matrix3(1.0f, 0.0f, 0.0f,
                                0.0f, 1.0f, 0.0f,
                                0.0f, 0.0f, 1.0f);
        }

        //To create a scale matrix
        public Matrix3 scale(double x, double y, double z)
        {
            return new Matrix3(x, 0.0f, 0.0f,
                                0.0f, y, 0.0f,
                                0.0f, 0.0f, z);
        }

        //To create a rotate matrix
        public Matrix3 roate(Vector3 axis, double angle)
        {
            Vector3 vec = new Vector3(axis);
            Vector3.normalize(vec);
            double x = vec.x;
            double y = vec.y;
            double z = vec.z;

            double cos = (double)Math.Cos(angle);
            double sin = (double)Math.Sin(angle);

            Matrix3 mCross = new Matrix3(0.0f, z, -y,
                                        -z, 0.0f, x,
                                        y, -x, 0.0f);

            Matrix3 mTensor = new Matrix3(x * x, x * y, x * z,
                                        y * x, y * y, y * z,
                                        z * x, z * y, z * z);

            return Matrix3.add(Matrix3.add(
                    Matrix3.multiply(cos, Matrix3.identity())
                    , Matrix3.multiply(sin, mCross)),
                    Matrix3.multiply(1 - cos, mTensor));
        }

    }

    [Serializable]
    public class Vector3
    {
        private static string TAG = "Vector3";
        public double x = 0.0F;
        public double y = 0.0F;
        public double z = 0.0F;

        //    public enum Axis {
        //        X, Y, Z
        //    }
        //Unit vectors oriented to each axis
        public static Vector3 X = new Vector3(1, 0, 0);
        public static Vector3 Y = new Vector3(0, 1, 0);
        public static Vector3 Z = new Vector3(0, 0, 1);
        public static Vector3 NEG_X = new Vector3(-1, 0, 0);
        public static Vector3 NEG_Y = new Vector3(0, -1, 0);
        public static Vector3 NEG_Z = new Vector3(0, 0, -1);
        public static Vector3 ZERO = new Vector3(0, 0, 0);
        public static Vector3 ONE = new Vector3(1, 1, 1);


        public Vector3()
        {
            x = 0.0;
            y = 0.0;
            z = 0.0;
        }

        public Vector3(double x, double y, double z)
        {
            this.x = x;
            this.y = y;
            this.z = z;
        }


        public Vector3(Vector3 vector3)
        {
            this.x = vector3.x;
            this.y = vector3.y;
            this.z = vector3.z;
        }
        public double[] ToDouble()
        {
            double[] tmpDouble = new double[3];
            tmpDouble[0] = this.x;
            tmpDouble[1] = this.y;
            tmpDouble[2] = this.z;
            return tmpDouble;

        }
        public void set(Vector3 vector3)
        {
            this.x = vector3.x;
            this.y = vector3.y;
            this.z = vector3.z;
        }
        public Vector3 multiply(Vector3 another)
        {
            this.x *= another.x;
            this.y *= another.y;
            this.z *= another.z;
            return this;
        }
        public Vector3 multiply(double scalar)
        {
            this.x *= scalar;
            this.y *= scalar;
            this.z *= scalar;
            return this;
        }
        public static Vector3 multiply(double scalar, Vector3 vec)
        {
            return new Vector3(scalar * vec.x, scalar * vec.y, scalar * vec.z);
        }

        public Vector3 multiply(double x, double y, double z)
        {
            this.x *= x;
            this.y *= y;
            this.z *= z;
            return this;
        }


        public Vector3 multiply(double[] matrix4)
        {
            double vx = x, vy = y, vz = z;
            this.x = vx * matrix4[0] + vy * matrix4[4] + vz * matrix4[8] + matrix4[12];
            this.y = vx * matrix4[1] + vy * matrix4[5] + vz * matrix4[9] + matrix4[13];
            this.z = vx * matrix4[2] + vy * matrix4[6] + vz * matrix4[10] + matrix4[14];

            return this;
        }

        public void add(Vector3 another)
        {
            this.x += another.x;
            this.y += another.y;
            this.z += another.z;
        }

        public void sub(Vector3 another)
        {
            this.x -= another.x;
            this.y -= another.y;
            this.z -= another.z;
        }

        public static Vector3 sub(Vector3 a, Vector3 b)
        {
            return new Vector3(a.x - b.x, a.y - b.y, a.z - b.z);
        }

        public static void plus(Vector3 sum, Vector3 a, Vector3 b)
        {
            sum.x = a.x + b.x;
            sum.y = a.y + b.y;
            sum.z = a.z + b.z;
        }
        public static void calcDirVec(Vector3 dirVec, Vector3 start, Vector3 end)
        {
            dirVec.x = end.x - start.x;
            dirVec.y = end.y - start.y;
            dirVec.z = end.z - start.z;
        }
        public static double dot(Vector3 a, Vector3 b)
        {
            return (a.x * b.x + a.y * b.y + a.z * b.z);
        }
        public double dot(Vector3 v)
        {
            return x * v.x + y * v.y + z * v.z;
        }
        //叉乘。新向量垂直于输入的两个向量所在的平面，并且其长度（或模）等于输入向量构成的平行四边形的面积。
        public static void cross(Vector3 result, Vector3 one, Vector3 other)
        {
            result.x = one.y * other.z - one.z * other.y;
            result.y = one.z * other.x - one.x * other.z;
            result.z = one.x * other.y - one.y * other.x;
        }
        public Vector3 cross(Vector3 one, Vector3 other)
        {
            return new Vector3(one.y * other.z - one.z * other.y,
                               one.z * other.x - one.x * other.z,
                               one.x * other.y - one.y * other.x);
        }

        public void set(double[] point)
        {
            if (point.Length < 0)
            {
                //Log.e(TAG, "array size < 0");
                return;
            }
            else if (point.Length != 3)
            {
                // Log.i(TAG, "array size not equal to 3");
            }
            this.x = point[0];
            this.y = point[1];
            this.z = point[2];

        }
        public void set(double x, double y, double z)
        {
            this.x = x;
            this.y = y;
            this.z = z;
        }
        public void add(double x, double y, double z)
        {
            this.x += x;
            this.y += y;
            this.z += z;
        }
        // 加法运算符重载
        public static Vector3 operator +(Vector3 a, Vector3 b)
        {
            return new Vector3(a.x + b.x, a.y + b.y, a.z + b.z);
        }
        /**
         * Matrix divide a num
         * @author ytan  2016/08/12
         */

        public void divide(double num)
        {
            this.x /= num;
            this.y /= num;
            this.z /= num;
        }

        public String toString()
        {
            String str = "";
            str += "[" + this.x + ", " + this.y + ", " + this.z + "]";
            return str;
        }

        //计算空间中两点距离
        public static double calcDistance(Vector3 start, Vector3 end)
        {
            double dx = end.x - start.x;
            double dy = end.y - start.y;
            double dz = end.z - start.z;

            return Math.Sqrt(dx * dx + dy * dy + dz * dz);
        }

        public static void normalize(Vector3 n)
        {
            double mag = Math.Sqrt(n.x * n.x + n.y * n.y + n.z * n.z);
            if (mag != 0 && mag != 1)
            {
                double mod = 1 / mag;
                n.x *= mod;
                n.y *= mod;
                n.z *= mod;
            }
        }
        public void normalize()
        {
            double mag = Math.Sqrt(x * x + y * y + z * z);
            if (mag != 0 && mag != 1)
            {
                double mod = 1 / mag;
                x *= mod;
                y *= mod;
                z *= mod;
            }
        }

        //    public Vector3 rotateBy(Vector4 quaternion) {
        //        this.set(quaternion.multiply(this));
        //        return this;
        //    }

        //    public Vector3 clone() {
        //        return new Vector3(x, y, z);
        //    }

        public double getLength()
        {
            return (double)Math.Sqrt(x * x + y * y + z * z);
        }
        public static double getLength(double x, double y, double z)
        {
            return (double)Math.Sqrt(x * x + y * y + z * z);
        }

        public void inverse()
        {
            x = -x;
            y = -y;
            z = -z;
        }

        public bool isUnit()
        {
            return Math.Abs(getLength() - 1) < 1e-8 * 1e-8;
        }


        public Object clone()
        {
            // TODO Auto-generated method stub
            Vector3 vector3 = (Vector3)this.clone();
            return vector3;
        }

        public static Vector3 AngleAxis(double angle1, Vector3 axis)
        {
            axis.normalize();
            double angle = angle1 * Math.PI / 180;
            double c = Math.Cos(angle), s = Math.Sin(angle);
            return new Vector3(
                c * axis.x * axis.x + (1 - c) * axis.dot(axis) + s * axis.z,
                c * axis.x * axis.y - s * axis.z + (1 - c) * axis.dot(new Vector3(0, axis.z, -axis.y)),
                c * axis.x * axis.z + s * axis.y + (1 - c) * axis.dot(new Vector3(-axis.y, 0, axis.x))
            );
        }
    }

}
